/*
 * @Author: huirui@huanqiu.com
 * @Date: 2024-07-30 17:23:43
 * @LastEditors: huirui@huanqiu.com
 * @LastEditTime: 2024-10-09 17:14:08
 * @Description: 视频号抓取
 */
const puppeteer = require("puppeteer-extra");
const StealthPlugin = require("puppeteer-extra-plugin-stealth");
puppeteer.use(StealthPlugin());
const dayjs = require("dayjs");
const axios = require("axios");
const notification = require("../../utils/notification");
const logger = require("../../utils/logger");
const { sendWechatMessage } = require("../../utils");
const md5 = require("md5");
const fs = require("fs");
const path = require("path");
const userDataDir = process.env.WEB_CONFIG_USER_DATA_DIR;
const executablePath = process.env.WEB_CONFIG_EXECUTABLE_PATH;
const { publishCallback } = require("../../utils");
const getChannelsVideoInfo = async (params) => {
  const browser = await puppeteer.launch({
    headless: "new",
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
    ],
    ignoreHTTPSErrors: true,
  });
  let allData = [];
  try {
    const page = await browser.newPage();
    await page.goto("https://channels.weixin.qq.com/platform", {
      waitUntil: "networkidle0",
    });

    if (await isNotLogin(page)) {
      logger.info("未登录，等待用户登录...");
      await notification(
        "视频号",
        `${process.env.NODE_ENV}环境的视频号数据获取失败`,
        "请在10分钟内登录"
      );

      const qrcodeBase64 = await getQrcodeBase64(page);
      if (qrcodeBase64) {
        const qrcodeBuffer = Buffer.from(qrcodeBase64, "base64");
        logger.info(`获取二维码成功`);
        await sendWechatMessage({
          msgtype: "image",
          image: {
            base64: qrcodeBase64,
            md5: md5(qrcodeBuffer),
          },
        });
      } else {
        logger.error("无法获取二维码");
      }

      let loginSuccess = false;
      const startTime = Date.now();
      const timeoutDuration = 10 * 60 * 1000; // 10分钟
      let previousQRCodeStatus = null;

      while (!loginSuccess && Date.now() - startTime < timeoutDuration) {
        const status = await checkAndRefreshQRCode(page);

        switch (status) {
          case "refreshed":
            logger.info("二维码已刷新，等待用户扫码...");
            break;
          case "valid":
            if (previousQRCodeStatus === "scanned") {
              logger.info("检测到用户取消了之前的扫码，重新获取二维码...");
              await notification(
                "视频号",
                `${process.env.NODE_ENV}环境用户取消扫码，正在获取最新二维码`,
                "请重新扫码"
              );
              const newQrcodeBase64 = await getQrcodeBase64(page);
              if (newQrcodeBase64) {
                const qrcodeBuffer = Buffer.from(newQrcodeBase64, "base64");
                logger.info("获取新二维码成功");
                await sendWechatMessage({
                  msgtype: "image",
                  image: {
                    base64: newQrcodeBase64,
                    md5: md5(qrcodeBuffer),
                  },
                });
              } else {
                logger.error("无法获取新二维码");
              }
            } else {
              logger.info("二维码有效，等待用户扫码...");
            }
            break;
          case "scanned":
            logger.info("用户已扫码，等待确认...");
            break;
          case "expired":
            logger.info("二维码已过期，将在下一次循环中刷新");
            break;
          default:
            logger.info("等待用户扫码...");
        }

        previousQRCodeStatus = status;

        if (!(await isNotLogin(page))) {
          loginSuccess = true;
          logger.info("检测到登录成功");
          await notification(
            "视频号",
            `${process.env.NODE_ENV}环境的视频号数据获取成功`,
            "登录成功"
          );
          break;
        }

        await new Promise((resolve) => setTimeout(resolve, 2000)); // 每2秒检查一次
      }

      if (!loginSuccess) {
        logger.warn("登录等待超时（10分钟），正在关闭浏览器");
        await notification(
          "视频号",
          `${process.env.NODE_ENV}环境的视频号登录失败`,
          "等待超时"
        );
        throw new Error("登录超时");
      }
    }

    logger.info("已登录");

    // 创建一个 Promise 来处理请求拦截
    const interceptPromise = new Promise((resolve, reject) => {
      page.on("request", async (interceptedRequest) => {
        const url = interceptedRequest.url();
        if (
          url.includes(
            "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/statistic/post_list"
          )
        ) {
          const method = interceptedRequest.method();
          const headers = interceptedRequest.headers();
          const postData = interceptedRequest.postData();

          if (method === "POST" && postData) {
            let modifiedPostData = JSON.parse(postData);
            // 根据传入的参数确定日期范围
            let startDate;
            if (params.update_type === "highFrequency") {
              startDate = dayjs().subtract(7, "day").unix();
            } else if (params.interval) {
              const days = parseInt(params.interval);
              startDate = dayjs().subtract(days, "day").unix();
            } else {
              // 默认2024年1月1日的秒数
              startDate = dayjs("2024-01-01").unix();
            }
            modifiedPostData.startTime = startDate;

            let allData = [];
            let hasMore = true;
            let pageIndex = 1;
            let totalCount = 0;

            while (hasMore) {
              await new Promise((resolve) => setTimeout(resolve, 5000));
              modifiedPostData.currentPage = pageIndex;
              modifiedPostData.timestamp = Date.now().toString();

              try {
                const response = await axios({
                  url: url,
                  method: "POST",
                  headers: headers,
                  data: modifiedPostData,
                });

                if (response.status >= 200 && response.status < 300) {
                  if (response.data.errCode === 0) {
                    const { list, totalCount: total } = response.data.data;
                    totalCount = total; // 更新总数

                    const newData = list.map((item) => ({
                      title: item.desc.description,
                      cover: JSON.stringify([item.desc.media[0].coverUrl]),
                      //获取url query 参数 encfilekey 的 value，使用new URLSearchParams
                      id: new URLSearchParams(
                        item.desc.media[0].url.split("?")[1]
                      ).get("encfilekey"),
                      video_path: item.desc.media[0].url,
                      post_id: item.exportId,
                      object_id: item.objectId,
                      publish_time: dayjs(item.createTime * 1000).format(
                        "YYYY-MM-DD HH:mm:ss"
                      ),
                      read_count: item.readCount,
                      recommend_count: item.likeCount,
                      like_count: item.favCount,
                      comment_count: item.commentCount,
                      follow_count: item.followCount,
                      share_count: item.forwardAggregationCount,
                      forward_count: item.forwardCount,
                      complete_read_rate:
                        ((item.fullPlayRate || 0) * 100).toFixed(2) + "%",
                      avg_stay_time: parseFloat(
                        (item.avgPlayTimeSec || 0).toFixed(2)
                      ),
                    }));
                    allData = allData.concat(newData);
                    logger.info(
                      `获取第 ${pageIndex} 页数据，共 ${newData.length} 条，总数 ${totalCount} 条`
                    );

                    // 判断是否到达最后一页
                    if (allData.length >= totalCount) {
                      hasMore = false;
                    } else {
                      pageIndex++;
                    }
                  } else {
                    logger.error(`请求失败: ${response.data.errMsg}`);
                    reject(new Error(response.data.errMsg));
                    break;
                  }
                } else {
                  logger.error(
                    `请求失败: ${response.status}-${response.statusText}`
                  );
                  reject(
                    new Error(`${response.status}-${response.statusText}`)
                  );
                  break;
                }
              } catch (error) {
                logger.error(`请求发生错误: ${error.message}`);
                reject(error);
                break;
              }
            }
            resolve(allData);

            interceptedRequest.abort();
          } else {
            interceptedRequest.continue();
          }
        } else {
          interceptedRequest.continue();
        }
      });
    });

    await page.setRequestInterception(true);

    await page.evaluate(() => {
      const spans = document.querySelectorAll("span");
      for (const span of spans) {
        if (span.textContent.includes("视频数据")) {
          span.click();
          return;
        }
      }
      throw new Error('未找到包含"视频数据"的 span 元素');
    });
    await new Promise((resolve) => setTimeout(resolve, 3000));

    await page.evaluate(() => {
      const aTags = document.querySelectorAll("a");
      for (const aTag of aTags) {
        if (aTag.textContent.includes("单篇视频")) {
          aTag.click();
          return;
        }
      }
      throw new Error('未找到包含"单篇视频"的 a 标签');
    });

    // 等待截 Promise 完成
    const res = await interceptPromise;
    return res;
  } catch (err) {
    logger.error(`发生错误: ${err.message}`);
    return [];
  } finally {
    await browser.close();
  }
};

// 辅助函数: 检查是否登录
async function isNotLogin(page) {
  try {
    return await page.evaluate(async () => {
      // 检查是否存在admin-area，只有登录后才会出现的元素
      const loggedInElement = document.querySelector(".admin-area");
      return !loggedInElement;
    });
  } catch (error) {
    if (error.message.includes("Execution context was destroyed")) {
      // 如果执行上下文被销毁,可能是因为登录成功导致页面刷新
      return false;
    }
    throw error; // 如果是其他错误,则抛出
  }
}

//获取页面的iframe标签内的二维码类名为qrcode的图片src的base64
async function getQrcodeBase64(page) {
  return await page.evaluate(() => {
    const iframe = document.querySelector("iframe");
    if (!iframe) {
      console.error("未找到iframe元素");
      return null;
    }

    const qrcode = iframe.contentDocument.querySelector(".qrcode");
    if (!qrcode) {
      console.error("未在iframe中找到.qrcode元素");
      return null;
    }

    if (!qrcode.src) {
      console.error(".qrcode元素没有src属性");
      return null;
    }

    const srcParts = qrcode.src.split(",");
    if (srcParts.length < 2) {
      console.error("qrcode.src格式不正确");
      return null;
    }

    return srcParts[1];
  });
}
// 检查二维码状态并刷新
async function checkAndRefreshQRCode(page) {
  const status = await page.evaluate(() => {
    const iframe = document.querySelector("iframe");
    if (!iframe) return "no_iframe";
    const qrcodeElement = iframe.contentDocument.querySelector(".qrcode");
    const refreshText = iframe.contentDocument.querySelector(".mask.show");

    if (
      qrcodeElement &&
      qrcodeElement.classList.contains("opacity") &&
      refreshText
    ) {
      if (refreshText.textContent.includes("点击刷新")) {
        return "expired";
      } else if (refreshText.textContent.includes("已扫码")) {
        return "scanned";
      }
    } else if (qrcodeElement && !qrcodeElement.classList.contains("opacity")) {
      return "valid";
    }
    return "unknown";
  });

  if (status === "expired") {
    logger.info("二维码已过期，点击刷新按钮");
    await notification(
      "视频号",
      `${process.env.NODE_ENV}环境的二维码已过期`,
      "正在获取新二维码"
    );

    await page.evaluate(() => {
      const iframe = document.querySelector("iframe");
      if (iframe) {
        const refreshButton =
          iframe.contentDocument.querySelector(".refresh-wrap");
        if (refreshButton) refreshButton.click();
      }
    });

    // 等待新二维码加载
    await new Promise((resolve) => setTimeout(resolve, 2000));

    // 获取并发送新二维码
    const newQrcodeBase64 = await getQrcodeBase64(page);
    if (newQrcodeBase64) {
      const qrcodeBuffer = Buffer.from(newQrcodeBase64, "base64");
      logger.info("获取新二维码成功");
      await sendWechatMessage({
        msgtype: "image",
        image: {
          base64: newQrcodeBase64,
          md5: md5(qrcodeBuffer),
        },
      });
    }

    return "refreshed";
  }

  return status;
}

// 视频号发布

// 在文件顶部定义一个全局变量来跟踪是否已设置请求拦截
let isInterceptionSet = false;

// 创建一个统一的请求拦截处理函数
function setupRequestInterception(page) {
  if (isInterceptionSet) {
    return; // 如果已经设置过拦截，直接返回
  }

  page.setRequestInterception(true);
  page.on("request", (request) => {
    const url = request.url();

    if (
      url.includes(
        "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/collection/get_collection_list"
      )
    ) {
      const data = JSON.parse(request.postData());
      data.pageSize = 1000;
      request.continue({
        method: request.method(),
        postData: JSON.stringify(data),
        headers: { ...request.headers() },
      });
    } else if (
      url.includes(
        "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_create"
      )
    ) {
      if (page.effectiveTime) {
        logger.info(`设置定时发送时间，${page.effectiveTime}`);
        // 打印 request.postData() 的类型
        console.log(typeof request.postData());
        console.log(Object.prototype.toString.call(request.postData()));
        try {
          let data = request.postData();
          data = data.replace(
            /}(?!\s*[,}])/g,
            `,"effectiveTime":${JSON.stringify(page.effectiveTime)}}`
          );
          request.continue({
            postData: data,
          });
        } catch (error) {
          logger.error(`解析请求数据时出错: ${error.message}`);
          return request.continue();
        }
      } else {
        request.continue();
      }
    } else {
      request.continue();
    }
  });

  isInterceptionSet = true;
}

async function publishVideo(params) {
  //按照getChannelsVideoInfo的方式，打开浏览器，到判断是否登录，没登录扫码登录
  const browser = await puppeteer.launch({
    headless: "new",
    headless: false,
    userDataDir,
    executablePath,
    defaultViewport: null,
    args: [
      "--no-sandbox",
      "--disable-setuid-sandbox",
      "--disable-features=site-per-process",
      "--start-maximized",
      // "--auto-open-devtools-for-tabs",
    ],
    ignoreHTTPSErrors: true,
  });
  let allData = [];
  try {
    const page = await browser.newPage();
    await page.goto("https://channels.weixin.qq.com/platform", {
      waitUntil: "networkidle0",
    });

    if (await isNotLogin(page)) {
      logger.info("未登录，等待用户登录...");
      await notification(
        "视频号",
        `${process.env.NODE_ENV}环境的视频号数据获取失败`,
        "请在10分钟内登录"
      );

      const qrcodeBase64 = await getQrcodeBase64(page);
      if (qrcodeBase64) {
        const qrcodeBuffer = Buffer.from(qrcodeBase64, "base64");
        logger.info(`获取二维码成功`);
        await sendWechatMessage({
          msgtype: "image",
          image: {
            base64: qrcodeBase64,
            md5: md5(qrcodeBuffer),
          },
        });
      } else {
        logger.error("无法获取二维码");
      }

      let loginSuccess = false;
      const startTime = Date.now();
      const timeoutDuration = 10 * 60 * 1000; // 10分钟
      let previousQRCodeStatus = null;

      while (!loginSuccess && Date.now() - startTime < timeoutDuration) {
        const status = await checkAndRefreshQRCode(page);

        switch (status) {
          case "refreshed":
            logger.info("二维码已刷新，等待用户扫码...");
            break;
          case "valid":
            if (previousQRCodeStatus === "scanned") {
              logger.info("检测到用户取消了之前的扫码，重新获取二维码...");
              await notification(
                "视频号",
                `${process.env.NODE_ENV}环境用户取消扫码，正在获取最新二维码`,
                "请重新扫码"
              );
              const newQrcodeBase64 = await getQrcodeBase64(page);
              if (newQrcodeBase64) {
                const qrcodeBuffer = Buffer.from(newQrcodeBase64, "base64");
                logger.info("获取新二维码成功");
                await sendWechatMessage({
                  msgtype: "image",
                  image: {
                    base64: newQrcodeBase64,
                    md5: md5(qrcodeBuffer),
                  },
                });
              } else {
                logger.error("无法获取新二维码");
              }
            } else {
              logger.info("二维码有效，等待用户扫码...");
            }
            break;
          case "scanned":
            logger.info("用户已扫码，等待确认...");
            break;
          case "expired":
            logger.info("二维码已过期，将在下一次循环中刷新");
            break;
          default:
            logger.info("等待用户扫码...");
        }

        previousQRCodeStatus = status;

        if (!(await isNotLogin(page))) {
          loginSuccess = true;
          logger.info("检测到登录成功");
          await notification(
            "视频号",
            `${process.env.NODE_ENV}环境的视频号数据获取成功`,
            "登录成功"
          );
          break;
        }

        await new Promise((resolve) => setTimeout(resolve, 2000)); // 每2秒检查一次
      }

      if (!loginSuccess) {
        logger.warn("登录等待超时（10分钟），正在关闭浏览器");
        await notification(
          "视频号",
          `${process.env.NODE_ENV}环境的视频号登录失败`,
          "等待超时"
        );
        throw new Error("登录超时");
      }
    }

    logger.info("已登录");
    // 先下载video视频，再点击上传视频按钮，进行上传
    const videoPath = await downloadVideo(params.video);
    const coverPath = await downloadCover(params.cover);
    await new Promise((resolve) => setTimeout(resolve, 3000));
    // 点击发表视频按钮
    await page.evaluate(() => {
      const buttons = document.querySelectorAll("button");
      for (const button of buttons) {
        if (button.textContent.includes("发表视频")) {
          button.click();
          return;
        }
      }
      throw new Error('未找到包含"发表视频"的 button 元素');
    });
    /***
     * "params":{
        "collection": "",
        "cover": "https://rstest.huanqiucdn.cn/wf221/191e4465ddf31kit4q8u.png",
        "post_id": 172,
        "summary": "！",
        "talk": [],
        "title": "极限运动",
        "video": "https://rstest.huanqiucdn.cn/wf221/fc2fcf2c-9798-4b84-93e2-04ce3848f033.mp4"
      }
     */
    // 上传视频
    await uploadVideo(page, videoPath);
    await uploadCover(page, coverPath);
    // 输入话题
    await inputTaggedContent(page, params.talk, true);
    // 输入@用户
    await inputTaggedContent(page, params.at_users, false);
    // 输入视频描述
    await inputVideoDesc(page, params.summary);
    // 选择合集
    await selectCollection(page, params.collection);
    // 选择活动
    await selectActivity(page, params.activity);
    // 输入端标题 short_title
    await inputShortTitle(page, params.short_title);
    // 点击发表按钮
    await clickPublishButton(page);
    // 定时发送
    // await handleScheduledPublish(page, params.effective_time);
    // 等待发表成功
    await handlePublishSuccess(page);
    // 发送成功，回调
    const id = await callback(page);
    logger.info(`发布成功，post_id: ${id}`);
    return id;
  } catch (err) {
    logger.error(`发生错误: ${err.message}`);
    throw new Error(err.message);
  } finally {
    await browser.close();
  }
}

// 下载视频
async function downloadVideo(videoUrl) {
  try {
    logger.info(`开始下载视频: ${videoUrl}`);

    // 创建保存视频的目���
    const dir = path.join(
      __dirname,
      `../uploads/video/${dayjs().format("YYYY-MM-DD")}`
    );
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }

    // 获取视频文件名
    const videoName = path.basename(new URL(videoUrl).pathname);
    const videoPath = path.join(dir, videoName);

    // 下载视频
    const response = await axios({
      method: "GET",
      url: videoUrl,
      responseType: "stream",
    });

    // 将视频保存到本地
    const writer = fs.createWriteStream(videoPath);
    response.data.pipe(writer);

    return new Promise((resolve, reject) => {
      writer.on("finish", () => {
        logger.info(`视频下载成功: ${videoPath}`);
        resolve(videoPath);
      });
      writer.on("error", reject);
    });
  } catch (error) {
    logger.error(`视频下载失败: ${error.message}`);
    throw error;
  }
}
//上传视频
async function uploadVideo(page, videoPath) {
  uploadInput = await page.waitForSelector("input[type='file'][accept*='mp4']");
  logger.info(`开始上传视频: ${videoPath}`);
  try {
    await uploadInput.uploadFile(videoPath);
    // await page.waitForSelector("#fullScreenVideo", { timeout: 100000 });
    //#TAG:上传视频最长15分钟超时
    await page.waitForResponse(
      (response) =>
        response
          .url()
          .includes(
            "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_clip_video_result"
          ),
      { timeout: 900000 }
    );
    await new Promise((resolve) => setTimeout(resolve, 1500));
    logger.info(`视频上传成功`);
  } catch (error) {
    logger.error(`视频上传失败: ${error.message}`);
    throw error;
  }

  await new Promise((resolve) => setTimeout(resolve, 3000));
}
// 下载封面
async function downloadCover(coverUrl) {
  try {
    logger.info(`开始下载封面: ${coverUrl}`);

    // 创建保存封面的目录
    const dir = path.join(
      __dirname,
      `../uploads/video/${dayjs().format("YYYY-MM-DD")}`
    );
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }

    // 获取封面文件名
    const coverName = path.basename(new URL(coverUrl).pathname);
    const coverPath = path.join(dir, coverName);

    // 下载封面
    const response = await axios({
      method: "GET",
      url: coverUrl,
      responseType: "stream",
    });

    // 将封面保存到本地
    const writer = fs.createWriteStream(coverPath);
    response.data.pipe(writer);

    return new Promise((resolve, reject) => {
      writer.on("finish", () => {
        logger.info(`封面下载成功: ${coverPath}`);
        resolve(coverPath);
      });
      writer.on("error", reject);
    });
  } catch (error) {
    logger.error(`封面下载失败: ${error.message}`);
    throw error;
  }
}
// 上传封面
async function uploadCover(page, coverPath) {
  await page.evaluate(() => {
    // 等待 更换封面 出现，说明视频上传成功
    const uploadImage = document.querySelectorAll(".tag-inner");
    for (const image of uploadImage) {
      if (image.textContent.includes("更换封面")) {
        image.click();
        return;
      }
    }
    throw new Error("未找到封面上传按钮");
  });
  logger.info(`开始上传封面: ${coverPath}`);
  uploadInput = await page.waitForSelector("input[type='file'][accept*='jpg']");
  await uploadInput.uploadFile(coverPath);
  await new Promise((resolve) => setTimeout(resolve, 10000));
  logger.info(`封面上传成功`);
  // 选择内容是 确定 的按钮点击
  await page.evaluate(() => {
    const buttons = document.querySelectorAll("button");
    for (const button of buttons) {
      if (button.textContent.includes("确定")) {
        button.click();
        return;
      }
    }
  });
  // 选完封面点击 确认
  await page.evaluate(() => {
    const buttons = document.querySelectorAll(
      ".finder-common-dialog.post-media-cover-dialog button"
    );
    for (const button of buttons) {
      if (button.textContent.includes("确认")) {
        button.click();
        return;
      }
    }
  });
}
// 输入话题, 话题是数组[话题1,话题2,话题3], 输入之后应该是 #话题1 #话题2 #话题3，每次输入一个话��后，需要添加个空格
async function inputTaggedContent(page, items, isTopics = true) {
  if (!items || items.length === 0 || !Array.isArray(items)) {
    return;
  }

  const inputSelector = ".input-editor";
  const prefix = isTopics ? "#" : "@";
  await page.waitForSelector(inputSelector);
  for (const item of items) {
    await page.focus(inputSelector);
    await page.type(inputSelector, `${prefix}${item} `);
  }
}
// 输入视频描述
async function inputVideoDesc(page, desc) {
  if (!desc || desc.length === 0) {
    return;
  }
  const inputSelector = ".input-editor";
  await page.focus(inputSelector);
  await page.type(inputSelector, desc);
}
// 选择合集
async function selectCollection(page, collection) {
  logger.info(`选择合集: ${collection}`);
  if (!collection || collection.length === 0) {
    return;
  }
  // interceptCollectionPostRequest(page, collection);
  setupRequestInterception(page);
  // 点击合集
  await page.evaluate(() => {
    //post-album-display-wrap
    const postAlbumDisplayWrap = document.querySelector(
      ".post-album-display-wrap"
    );
    console.log("postAlbumDisplayWrap", postAlbumDisplayWrap);
    if (postAlbumDisplayWrap) {
      postAlbumDisplayWrap.click();
    }
  });
  await new Promise((resolve) => setTimeout(resolve, 3000));
  // 选择合集, 把 collection 和 corCollection textContent 比较，如果相同，则点击
  await page.evaluate((collection) => {
    const collections = document.querySelectorAll(".name");
    for (const corCollection of collections) {
      if (corCollection.textContent == collection) {
        corCollection.click();
        return;
      }
    }
  }, collection);
}

// 检测集合的post网络请求，改写请求体参数pageSize 为 1000
function interceptCollectionPostRequest(page, collection) {
  page.setRequestInterception(true);
  page.on("request", (request) => {
    if (
      request
        .url()
        .includes(
          "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/collection/get_collection_list"
        )
    ) {
      const data = JSON.parse(request.postData());
      data.pageSize = 1000;
      request.continue({
        method: request.method(),
        postData: JSON.stringify(data),
        headers: {
          ...request.headers(),
        },
      });
    } else {
      request.continue();
    }
  });
}
// 选择活动
async function selectActivity(page, activity) {
  if (!activity || activity.length === 0) {
    return;
  }
  await page.evaluate(() => {
    const activity = document.querySelector(".activity-display-wrap");
    if (activity) {
      activity.click();
    }
  });
  // 直接赋值 活动名
  await page.evaluate((activity) => {
    const activityInput = document.querySelector(".activity-filter-wrap input");
    if (activityInput) {
      activityInput.value = activity;
    }
  }, activity);
  await page.type(".activity-filter-wrap input", " ");
  // 等待活动列表的请求结束
  await page.waitForResponse((response) =>
    response
      .url()
      .includes(
        "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_search_event"
      )
  );
  const activitys = await page.$$(
    ".activity-filter-wrap .common-option-list-wrap .option-item"
  );
  if (activitys.length > 1) {
    await page.evaluate((selector) => {
      const element = document.querySelectorAll(selector)[1];
      if (element) {
        console.log("选择活动", element);
        element.click();
      }
    }, ".activity-filter-wrap .common-option-list-wrap .option-item");
  } else {
    console.error("未找到第二个活动元素");
  }
}
// 输入端标题 short_title
async function inputShortTitle(page, short_title) {
  if (!short_title || short_title.length < 6) {
    logger.error("端标题太短，请输入6个字以上的端标题");
    return;
  }
  const inputSelector = ".post-short-title-wrap input";
  await page.focus(inputSelector);
  await page.type(inputSelector, short_title);
}
// 点击发表按钮
async function clickPublishButton(page) {
  await page.evaluate(() => {
    const buttons = document.querySelectorAll("button");
    const publishButton = Array.from(buttons).find((button) =>
      button.textContent.includes("发表")
    );
    if (publishButton) {
      publishButton.click();
      return;
    }
    logger.error("未找到发表按钮");
    throw new Error("未找到发表按钮");
  });
}
// 定时发送，通过判断是否有 effective_time 参数，如果有，则进行定时发送, 如果没有，则不进行定时发送,发送方法通过直接修改 https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_create 的 post 请求体参数
async function handleScheduledPublish(page, effective_time) {
  // 拦截请求
  page.effectiveTime = effective_time;
  setupRequestInterception(page);
}
// 等待发表成功
async function handlePublishSuccess(page) {
  return new Promise((resolve, reject) => {
    page.on("response", async (response) => {
      if (
        response
          .url()
          .includes(
            "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_create"
          )
      ) {
        try {
          const responseData = await response.json();
          if (responseData.errCode === 0) {
            logger.info("发表成功");
            resolve(true);
          } else {
            logger.error(`发表失败: ${responseData.errMsg}`);
            reject(new Error(responseData.errMsg));
          }
        } catch (error) {
          logger.error(`解析响应数据时出错: ${error.message}`);
          reject(error);
        }
      }
    });
  });
}
// 回调
async function callback(page) {
  return new Promise((resolve, reject) => {
    const responseHandler = async (response) => {
      if (
        response
          .url()
          .includes(
            "https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_list"
          )
      ) {
        const data = await response.json();
        const list = data.data.list;
        for (const item of list) {
          if (!item.effectiveTime) {
            resolve(item.exportId);
            return; // 中断循环
          }
        }
        resolve(null); // 如果没有找到，resolve null
      }
    };

    page.on("response", responseHandler);

    // 添加超时机制
    setTimeout(() => {
      page.off("response", responseHandler); // 移除事件监听
      resolve(null); // 超时后返回 null
    }, 10000); // 10秒超时
  });
}

exports.handleCommand = async (command, params, taskId) => {
  switch (command) {
    case "getVideos":
      const data = await getChannelsVideoInfo(params);
      return { data };
    case "publish":
      try {
        const result = await publishVideo(params);
        await publishCallback(params.post_id, 3, "发布成功", taskId, result);
        return { data: [result] };
      } catch (error) {
        logger.error(error);
        await publishCallback(params.post_id, 4, error.message, taskId, "");
        return { data: [] };
      }
    // 其他命令...
    default:
      throw new Error("Unsupported command");
  }
};
